package com.tian.widget

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.RecyclerView
import com.tian.util.view.FlingUtil

/**
 * @author tiansongtao, Email:tiansongtao@up366.com
 * @date 2022/12/12 13:37
 *
 * 用于 NestedScrollView 嵌套 RecyclerView, RecyclerView上部有HeadView, 最好使用 MaxHeightRecyclerView
 *
 * 设置RecyclerView为 NestedScrollView同样一屏高度，使HeadView就像是 RecyclerView一个Item一样
 */
class NestedScrollViewRecyclerView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
    NestedScrollView(context, attrs, defStyleAttr) {

    private val TAG = "NestedScrollViewRecyclerView"

    private var idRecyclerView = 0
    private var idHead = 0

    var recyclerView: RecyclerView? = null
        set(value) {
            field = value
            requestLayout()
        }

    var headView: View? = null
        set(value) {
            field = value
            requestLayout()
        }

    private var headHeight = 0

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context) : this(context, null)

    init {
        initAttrs(context, attrs, defStyleAttr)
    }

    private fun initAttrs(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
        attrs?.let {
            val typeArray = context.obtainStyledAttributes(it, R.styleable.NestedScrollViewRecyclerView)
            idHead = typeArray.getResourceId(R.styleable.NestedScrollViewRecyclerView_HeaderId, 0)
            idRecyclerView = typeArray.getResourceId(R.styleable.NestedScrollViewRecyclerView_RecyclerViewId, 0)
            typeArray.recycle()
        }
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        if (idHead != 0 && idRecyclerView != 0) {
            headView = findViewById(idHead)
            recyclerView = findViewById(idRecyclerView)
        } else if (headView == null || recyclerView == null) {
            Log.e(TAG, "onFinishInflate: HeadView or RecyclerView is null")
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val lp = recyclerView!!.layoutParams
        val height = MeasureSpec.getSize(heightMeasureSpec)
        if (recyclerView is MaxHeightRecyclerView) {
            (recyclerView as MaxHeightRecyclerView).maxHeight = height
        } else if (lp is ConstraintLayout.LayoutParams) {
            (lp as ConstraintLayout.LayoutParams).matchConstraintMaxHeight = height
        } else {
            lp.height = height
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        headHeight = headView!!.measuredHeight
    }


    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
        if (dy < 0 && scrollY == 0 && recyclerView!!.computeVerticalScrollOffset() == 0) {
            //下滑 滑到了顶部
            dispatchNestedScroll(0, 0, 0, dy, null)
        } else {
            //上滑
            if (scrollY < headHeight) {
                if (scrollY + dy < headHeight) {
                    scrollBy(0, dy)
                    consumed[1] = dy
                } else if (scrollY + dy > headHeight) {
                    val scrollViewNeedScrollY = headHeight - scrollY
                    scrollBy(0, scrollViewNeedScrollY)
                    consumed[1] = scrollViewNeedScrollY
                }
            }
        }
    }

    override fun fling(velocityY: Int) {
        val dy = FlingUtil.getDistanceByVelocity(context, velocityY)
        if (scrollY < headHeight) {
            if (scrollY + dy <= headHeight) {
                super.fling(velocityY)
            } else if (scrollY + dy > headHeight) {
                val scrollViewNeedScrollY = headHeight - scrollY
                //让NestedScrollView先处理所有的滚动事件
                val scrollViewNeedVelocity = FlingUtil.getVelocityByDistance(context, scrollViewNeedScrollY.toDouble())
                if (velocityY > 0) {
                    super.fling(scrollViewNeedVelocity)
                } else {
                    super.fling(-scrollViewNeedVelocity)
                }
                //把剩余的滚动事件交给RecyclerView处理
                val recyclerViewScrollY = dy - scrollViewNeedScrollY
                val recyclerViewNeedVelocity = FlingUtil.getVelocityByDistance(context, recyclerViewScrollY)
                if (velocityY > 0) {
                    recyclerView!!.fling(0, recyclerViewNeedVelocity)
                } else {
                    recyclerView!!.fling(0, -recyclerViewNeedVelocity)
                }
            }
        }
    }


}